/* ArrayValue.cs -- 
   Copyright (C) 2008  Casey Marshall.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */


using System;
using System.Collections.Generic;
using System.Text;

using SexpSharp;

namespace SexpSharp.RPC
{
	/// <summary>
	/// An array of values.
	/// </summary>
	public sealed class ArrayValue : IValue
	{
		private IList<IValue> _value;

		/// <summary>
		/// Constructs a new ArrayValue using the given value.
		/// </summary>
		///
		/// <param name="value">The array value.</param>
		public ArrayValue(IEnumerable<IValue> value)
		{
			this._value = new List<IValue>(value);
		}

		public ArrayValue()
		{
			_value = new List<IValue>();
		}

		public ArrayValue(Expression expr)
		{
			List l = expr as List;
			if (l == null)
				throw new ArgumentException("must be a list", "expr");
			if (l.Count < 1 || !(l.First is Atom))
				throw new ArgumentException("list must have at least one atom");
			if (l.First.ToString() != "array")
				throw new ArgumentException("first item of list must be 'array'");

			_value = new List<IValue>();
			foreach (Expression e in l.Rest)
			{
				_value.Add (Values.ExpressionToValue(e));
			}
		}

		public IList<IValue> Value
		{
			get { return _value; }
			set { value.GetType(); _value = value; }
		}

		public Expression ToExpression()
		{
			List l = new List();
			l.Add(new Atom(Values.ArrayName));
			foreach (IValue val in _value)
				l.Add(val.ToExpression());
			return l;
		}

		public override string ToString()
		{
			StringBuilder str = new StringBuilder();
			str.Append("(");
			bool first = true;
			foreach (IValue val in _value)
			{
				if (!first)
					str.Append(", ");
				str.Append(val);
			}
			str.Append(")");
			return str.ToString();
		}

		public bool Equals(IValue that)
		{
			 if (that is ArrayValue)
			 {
				  IList<IValue> val = ((ArrayValue) that)._value;
				  if (_value.Count != val.Count)
					   return false;
				  for (int i = 0; i < _value.Count; i++)
				  {
					   if (!_value[i].Equals(val[i]))
					   {
							return false;
					   }
				  }
				  return true;
			 }
			 return false;
		}

		public override bool Equals(object o)
		{
			 if (o is IValue)
				  return Equals((IValue) o);
			 return false;
		}

		public override int GetHashCode()
		{
			 int code = 0;
			 foreach (IValue v in _value)
				  code ^= v.GetHashCode();
			 return code;
		}
	}
}
